ВВЕРХ

Fuzzy Lookup для LibreOffice Calc

YLC Utilities logo

FUZZYLOOKUP() Описание

Все мы знаем хорошо известную функцию VLOOKUP(), которая помогает нам совмещать данные из разных таблиц. Однако данная функция имеет один существенный недостаток – она не может совмещать подобные значения, то есть если в слове допущена ошибка – то совпадения уже не будет.

Чтобы иметь возможность совмещать приблизительные значения, мы можем создать собственную функцию. Давайте назовем ее FuzzyLookup().

Представим, что у нас есть два списка. И в том, и в другом примерно одни и те же элементы, но записаны они могут быть немного по-разному. Задача - подобрать каждому элементу в первом списке максимально схожий элемент из второго списка, т.е. реализовать поиск ближайшего максимально схожего текста.

Большой вопрос, в данном случае, что считать критерием "схожести". Просто количество совпадающих символов? Или количество совпадений, идущих подряд? Учитывать ли регистр символов или пробелы? Что делать с разным расположением слов во фразе? Вариантов много и однозначного решения нет – для каждой ситуации тот или иной будет лучше других.

В нашем случае мы реализуем самый простой вариант – поиск по максимальному количеству совпадений символов. Он не идеален, но для большинства ситуаций работает вполне надежно.


StarBASIC код для функции FuzzyLookup

Чтобы добавить функцию FuzzyLookup , откройте меню Tools - Macros - Edit Macros... , выберите Module1 и скопируйте следующий текст в модуль:


Function FuzzyLOOKUP(LookupValue As String, SrcTable As Variant, Optional SimThreshold As Single) As String 
  ' moonexcel.com.ua 
  Dim Str       As String  
  Dim CellArray As Variant
  Dim StrArray  As Variant
  
  If IsMissing(SimThreshold) Then SimThreshold  = 0
  
  Str      = LCase(LookupValue)
  StrArray = Split(Str)
  StrExt   = UBound(StrArray)  
            
  For Each Cell In SrcTable
                          
    CellArray = Split(LCase(Cell))
    CellExt   = UBound(CellArray)    	    
    CellRate  = 0
	
    ' Проверяем каждое слово в поисковой фразе 
    For x = 0 To StrExt 
    
      StrWord = StrArray(x)	  
      If Len(StrWord) = 0 Then GoTo continue_x
	  MaxStrWordRate = 0
	  
      ' Проверяем каждое слово в очередной ячейке из исходной таблицы значений 
      For i = 0 To CellExt
        
        CellWord = CellArray(i)
		If Len(CellWord) = 0 Then GoTo continue_i
   
        FindCharNum = OccurrenceNum(StrWord, CellWord)
        StrWordRate = FindCharNum / Max(Len(StrWord),Len(CellWord))
		
        If StrWordRate > MaxStrWordRate Then MaxStrWordRate = StrWordRate
		continue_i:
      Next i		    
		    		    
      CellRate = CellRate + MaxStrWordRate
	  continue_x:
    Next x               
        
    ' Сохраняем лучшее совпадение 
    If CellRate > MaxCellRate Then    
      MaxCellRate = CellRate
      BestCell    = Cell          
       
      FindCharNum = OccurrenceNum(Str, Cell)
      SimRate     = FindCharNum / Max(Len(Str),Len(Cell))
    End If       
        
  Next Cell
    
  IF SimRate >= SimThreshold Then 
    IF SimThreshold = -1 Then
      ReturnValue = BestCell + " (" + Format(SimRate, "0.00") + ")"
    ElseIf SimThreshold = -2 Then
      ReturnValue = Format(SimRate, "0.00")
    Else
      ReturnValue = BestCell
    End If
  Else 
    ReturnValue = ""
  End If    
  
  FuzzyLOOKUP = ReturnValue
End Function


Function OccurrenceNum(ByVal SourceString As String, ByVal TargetString As String)
  For i = 1 To Len(SourceString)	         		        	        
    ' Ищем вхождение каждого символа 
    Position = InStr(1, TargetString, Mid(SourceString, i, 1), 1)  
    ' Увеличиваем счетчик совпадений 
    If Position > 0 Then		  
      Count = Count + 1
      ' Удаляем найденный символ 
      TargetString = Left(TargetString, Position - 1) + Right(TargetString, Len(TargetString) - Position)   
    End If
  Next i    
  OccurrenceNum = Count
End Function


Function Max(ByVal value1 As Variant, ByVal value2 As Variant)  
  If value1 > value2 Then
	Result = value1
  Else
	Result = value2
  End If
  Max = Result
End Function

Далее, закройте Macro Editor и вернитесь на рабочий лист LibreOffice Calc - теперь вы можете воспользоваться нашей новой функцией FuzzyLookup() .

Использование расширения

Вы также можете воспользоваться функцией FUZZYLOOKUP() установив бесплатное расширение YouLibreCalc.oxt или его полнофункциональную версию YLC_Utilities.oxt .

После этого данная функция будет доступна во всех файлах, которые будут открыты в LibreOffice Calc.